{% extends "baseD.html" %}

{% block headtitle %}- View Scene{% endblock %}
{% block divtitle  %}- View Scene{% endblock %}

{% block css %}
	<link href="/live3dstatic/css/viewScene.css" rel="stylesheet" type="text/css" media="screen" />
{% endblock %}

{% block scripts %}
	<script type="text/javascript" src="/live3dstatic/scripts/helperFunctions.js"></script>
	<script type="text/javascript" src="/live3dstatic/scripts/earth.js"></script>
	<script type="text/javascript" src="/live3dstatic/scripts/canvas.js"></script>

	<script type="text/javascript" src="/live3dstatic/scripts/matrix.js"></script>
	<script type="text/javascript" src="/live3dstatic/scripts/calibration.js"></script>
	
	<script type="text/javascript" src="/live3dstatic/scripts/swfobject.js"></script>
	<script type="text/javascript" src="/live3dstatic/scripts/downloadify.min.js"></script>
	
	<script type="text/javascript">
		
		{% if calibration %}
		var calib;
		function initCalibration() {
			var M = new Matrix(4,3, [[{{calibration.m11}}, {{calibration.m12}}, {{calibration.m13}}, {{calibration.m14}}], 
							         [{{calibration.m21}}, {{calibration.m22}}, {{calibration.m23}}, {{calibration.m24}}],
									 [{{calibration.m31}}, {{calibration.m32}}, {{calibration.m33}}, {{calibration.m34}}]]
							   );
			var camCenter = {x: {{calibration.cameraX}}, y: {{calibration.cameraY}}, z: {{calibration.cameraZ}},
							lat: {{scene.cameraLatitude}}, lon: {{scene.cameraLongitude}}, alt: {{scene.cameraAltitude}}};
			var pitch = {{scene.cameraTilt}};
			var heading = {{scene.cameraHeading}};
			var origin = {lat: {{calibration.originLatitude}}, lon: {{calibration.originLongitude}}, alt: {{calibration.originAltitude}} };
			var width = {{scene.width}};
			var height = {{scene.height}};
			calib = new Calibration(M, camCenter, pitch, heading, origin, width, height)
			
		}
		{% endif %}
		
		function init3D() {			
		
			{% if scene.calibrated %}
				jumpToFull({{scene.cameraLatitude}}, {{scene.cameraLongitude}}, {{scene.cameraAltitude}}, {{scene.cameraRoll}}, {{scene.cameraTilt}}, {{scene.cameraHeading}});		
			{% endif %}
			
			{% if calibration %}
			initCalibration();
			{% endif %}
			
			// add a dot to see where we're getting the depth from.
			var screenOverlay = ge.createScreenOverlay('');
			var icon = ge.createIcon('');
			icon.setHref('http://www.projectlive3d.com/live3dstatic/images/8x8dot.png');
			screenOverlay.setIcon(icon);

			// Set the ScreenOverlay's position in the window
			screenOverlay.getOverlayXY().setXUnits(ge.UNITS_FRACTION);
			screenOverlay.getOverlayXY().setYUnits(ge.UNITS_FRACTION);
			screenOverlay.getOverlayXY().setX(0.5);
			screenOverlay.getOverlayXY().setY(0.5);
			
			ge.getFeatures().appendChild(screenOverlay);
			
			initCanvas();
			
		}
		
		var id;
		var data;
		var context;
		var w, h;
		var earthHeight;
		var earthWidth;
		var busy;
		var BLOCK_SIZE = 4;
		var MIN_DEPTH = 5;
		var MAX_DEPTH = 2500;
		var map;
		var stop;
		
		function initCanvas() {
			context = getContext();
			
			loadImage('{{scene.url}}', function(){
				context.fillStyle = 'red'
				context.strokeStyle = 'white'
				context.lineWidth = 1;

				w = document.getElementById('canvasObject').width;
				h = document.getElementById('canvasObject').height;

				context.fillRect(0, 0, w, h);			
			
				id = context.createImageData(1,1); // only do this once per page
				data  = id.data;                        // only do this once per page
			
				earthHeight = document.getElementById('map3d').clientHeight;
				earthWidth = document.getElementById('map3d').clientWidth;

			}, null);
			
			
			Downloadify.create(
				document.getElementById('download_button'), {
				swf: "live3dstatic/scripts/downloadify.swf",
				downloadImage: "live3dstatic/images/download.png",
				width: 100,
				height: 30,
				filename: "depth_{{scene.index}}.csv",
				data: toCSV,
			});
			
		}
		
		function getAllDepth() {
			context.fillRect(0, 0, w, h);			
			ge.getOptions().setFlyToSpeed(ge.SPEED_TELEPORT); 
			busy = false;
			map = new Array();
			stop = false;
			document.getElementById('gobutton').setAttribute('disabled')
		
			for (var col = 0; col < w; col += BLOCK_SIZE){
				map[col] = new Array();
				getColDepth(col);
			}
			document.getElementById('gobutton').removeAttribute('disabled')			
		}
		
		function getColDepth(col) {
			for (var row = 0; row < h; row += BLOCK_SIZE){
				setTimeout('getDepth(' + col +',' + row + ')', 1);
			}
		}
		
		function getDepth(u, v) {
			while(busy){
				if (stop){
					return;
				}	
			};
			busy = true;
			if (stop) {
				return;
			}
			// find the pitch and heading that moves the camera so that (u,v)
			// is in the center of the virtual camera.
			var ray = calib.uv2xyz(u,v, 50);
			var radius = Math.sqrt(ray.x * ray.x + ray.y * ray.y + ray.z * ray.z)
			var tiltRad = Math.acos(ray.z/radius)
			var headingRad = Math.atan2(ray.y, ray.x)
			var tiltDeg = 180 - tiltRad * 180 / PI;
			var headingDeg = 90 - headingRad * 180 / PI;


			// move the camera.
			var cam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
			cam.setLatitude(calib.camCenter.lat);
			cam.setLongitude(calib.camCenter.lon);
			cam.setAltitude(calib.camCenter.alt);
			cam.setRoll(0);
			cam.setTilt(tiltDeg);
			cam.setHeading(headingDeg);

			ge.getView().setAbstractView(cam);
			
			var geo = absoluteHitTestPercent(0.5, 0.5);
			
			if (geo != null) {				
				geo = absoluteHitTestPercent(0.5, 0.5);
				var d_lat = geo.lat - calib.origin.lat;
				var d_lon = geo.lon - calib.origin.lon;
				var z = geo.alt - calib.origin.alt;
				var x = d_lon * distance(calib.origin.lat, calib.origin.lon, 0, calib.origin.lat, calib.origin.lon + 0.00001, 0) / 0.00001;
				var y = d_lat * distance(calib.origin.lat, calib.origin.lon, 0, calib.origin.lat + 0.00001, calib.origin.lon, 0) / 0.00001;
				
				
				var depth = distance(geo.lat,           geo.lon,           geo.alt,
									calib.camCenter.lat,calib.camCenter.lon,calib.camCenter.alt);
				map[u][v] = x + "," + y + "," + z;
				
				var maxD = Math.log(MAX_DEPTH);
				var minD = Math.log(MIN_DEPTH);				    
				var color = 255 - Math.round(((Math.log(depth) - minD) / (maxD - minD)) * 255);
				var rgba = [color, color, color, 255];

			} else {
				rgba = [100, 100, 255, 255];
				map[u][v] = "Inf,Inf,Inf";
				
			}
			for (var i = 0; i < BLOCK_SIZE; i++){
				for (var j = 0; j < BLOCK_SIZE; j++){
					drawPoint(u+i, v+j, rgba[0], rgba[1], rgba[2], rgba[3]);
				}
			}
			busy = false;
		}
		
		function drawPoint(x, y, r, g, b, a) {
			data[0]   = r;
			data[1]   = g;
			data[2]   = b;
			data[3]   = a;
			context.putImageData( id, x, y );
		}
		
		function toCSV() {
			var contents = calib.camCenter.x + "," + calib.camCenter.y + "," + calib.camCenter.z + "," + calib.camCenter.lat + "," + calib.camCenter.lon + "\n";
			var M = calib.M;
			contents += M[0][0] + "," + M[0][1] + "," + M[0][2] + "," + M[0][3] + ",NaN\n"
			contents += M[1][0] + "," + M[1][1] + "," + M[1][2] + "," + M[1][3] + ",NaN\n"
			contents += M[2][0] + "," + M[2][1] + "," + M[2][2] + "," + M[2][3] + ",NaN\n"
			
			for (var u in map){
				for (var v in map[u]){
					contents += u + "," + v + "," + map[u][v] + "\n"
				}
			}
			return contents;
		}
		
		var contents
		function collectSamples(){
			// collect a 5x5 grid of depth samples.
			
			var meters_per_lon = distance(calib.origin.lat, calib.origin.lon, 0, calib.origin.lat, calib.origin.lon + 0.00001, 0) / 0.00001;
			var meters_per_lat = distance(calib.origin.lat, calib.origin.lon, 0, calib.origin.lat + 0.00001, calib.origin.lon, 0) / 0.00001;
			
			contents = "<pre>"
			var ray = calib.uv2xyz(w/2,h/2, 50);
			ray.x = ray.x - calib.camCenter.x;
			ray.y = ray.y - calib.camCenter.y;
			ray.z = ray.z - calib.camCenter.z;
			var mag = Math.sqrt(ray.x*ray.x + ray.y*ray.y + ray.z*ray.z);
			ray.x = ray.x / mag;
			ray.y = ray.y / mag;
			ray.z = ray.z / mag;
			contents += "optical_axis=[" + ray.x + ',' + ray.y + ',' + ray.z + '];\n'
			
			
			var cam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
			var alphas =   [0.0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1]
			var labels = ['x', 'y', 'z']
			for (var k in ['x', 'y', 'z']){
				contents += labels[k] + "=["
				for (var j in alphas){
					for (var i in alphas) {
						var u = alphas[i];
						var v = alphas[j]
						var geo = absoluteHitTestPercent(u, v);
					
						if (geo) {
							if (labels[k] == 'x'){
								var d_lon = geo.lon - cam.getLongitude();
								var x = d_lon * meters_per_lon;
								contents += ' ' + x
							} else if (labels[k] == 'y'){
								var d_lat = geo.lat - cam.getLatitude();
								var y = d_lat * meters_per_lat;
								contents += ' ' + y
							} else {
								var z = geo.alt - cam.getAltitude();
								contents += ' ' + z;
							}
						} else {
							contents += ' Inf'
						}
					}
					contents += '\n'
				}
				contents += '];\n';
			}
			contents += "</pre>"
			document.getElementById('samples').innerHTML = contents;
			
			
		}
		
	</script>
{% endblock %}

{% block onload %}
	googleInit();
{% endblock %}

{% block content %}

	<div id="page">
		<div id="leftside">
			<div class="group">
				<h3>
					{% if scene.name %}
						 {{scene.name}}
					{% endif %}
				</h3>
				{% if credit %}
					From <a href="{{credit}}">{{credit}}</a><br/>
				{% endif %}
		
				<div id="imageshadow">
					<img id="smallimage" src="{{ scene.url }}" alt="" />
				</div>
				
				<hr/>

				<p class='optionsheader'>Instructions</p>
				<div class='optionspanel'>

					Pixels <input type="text" onchange="MIN_DEPTH = Number(this.value)" value="5"> meters away shown as white. <br/>
					Pixels <input type="text" onchange="MAX_DEPTH = Number(this.value)" value="2500"> meters away shown as black. <br/>
					Block size: <input type="text" onchange="BLOCK_SIZE = Number(this.value)" value="4">
					<input type="button" id="gobutton" value="GO!" onclick="getAllDepth()">
					<input type="button" id="gobutton" value="STOP!" onclick="stop=true;">
					
					<span id="download_button"></span>
				</div>
				
				<div>
					<input type="button" value="Reset View" onclick="jumpToFull({{scene.cameraLatitude}}, {{scene.cameraLongitude}}, {{scene.cameraAltitude}}, {{scene.cameraRoll}}, {{scene.cameraTilt}}, {{scene.cameraHeading}});">
					<input type="button" value="Collect 20x20 Depth Samples" onclick="collectSamples();">
					Toggle Frustum: <input type="checkbox" id="frustumBox" style="cursor:pointer;" onchange="calib.toggleFrustum()"/>
                    <label for="edgeLength" style="margin-left:10px;">Length (meters): </label>
                    <input type="text" id="edgeLength" value="50" size="2" onfocus="this.select();" onchange="calib.updateFrustum()">
					<div id="samples">
					</div>
				</div>
				
			</div>
		</div><!-- end left side -->
	
		<div id="rightside">
			<div id="gecontainer">
				<div id='map3d'></div>
			</div>

			<br/>
			<input type="checkbox" onchange="toggleBuildings();" id="showBuildings" checked/>
			<label for="showBuildings">  Show Buildings </label>
			<input type="checkbox" onchange="toggleGrayBuildings();" id="showGrayBuildings" checked/>
			<label for="showGrayBuildings">  Show Gray Buildings </label>
			
			<br/>
			<canvas id='canvasObject' width='300' height='300'>
				Your browser does not support the canvas element, and cannot use this application.
			</canvas>
			<input type="hidden" id="sizeU">
			<input type="hidden" id="sizeV">
		</div> <!-- end rightside -->

		<div style="clear: both;"></div>
    </div><!-- end page --> 
{% endblock %}
		
{% block scripts2 %} {% endblock %}